#pragma once
#include "data/buff.h"
#include "data/container.h"
#include "data/ground.h"
#include "data/item.h"
#include "data/player.h"
#include "data/spell.h"
#include "data/unit.h"
#include "game.h"
#include <memory>

struct Api {
  // action
  void take_taxi(const std::string &dest);
  void go(float x, float y, float z);
  // ground
  uint8 bait_state(uint64 ptr);
  std::vector<std::shared_ptr<Ground>> grounds();
  // item
  std::vector<std::shared_ptr<Item>> equip_items();
  uint64 get_equip_item_ptr(uint32 slots) const;
  std::vector<std::shared_ptr<Item>> container_items();
  uint32 get_num_free_slots() const;
  uint32 get_container_num_slots(uint32 container_index) const;
  std::optional<Item> get_container_item(uint32 container_index,
                                         uint32 slots) const;
  std::optional<Item> get_container_item_by_id(uint64 id1, uint64 id2) const;
  uint64 get_container_item_ptr(uint32 container_index, uint32 slots) const;
  std::optional<Container> get_container(uint32 index) const;
  void load_item_type_cache();
  void save_item_type_cache();
  // unit
  // 这个方法应该每个角色只需执行一次, 所以最好就是存到 lua 全局变量
  std::unordered_map<std::string, Spell> spells();
  std::optional<Buff> get_buff(const std::string &name) const;
  std::optional<Buff> unit_get_buff(const uint64 unit_ptr,
                                    const std::string &name) const;
  bool has_buff(const std::string &buff_name) const;
  bool unit_has_buff(uint64 unit_ptr, const std::string &buff_name) const;
  // unit_ptr = 0 时表示 player
  std::unordered_map<std::string, Buff> buffs(uint64 unit_ptr = 0) const;
  std::shared_ptr<Unit> get_unit(const std::string &unit_name);
  std::optional<Unit> get_unit(uint64 id1, uint64 id2) const;
  std::vector<std::shared_ptr<Unit>> units();
  std::shared_ptr<Player> player() const;
  // basic
  float player_dist(float x, float y, float z);
  float dist(float x1, float y1, float z1, float x2, float y2, float z2);
  void set_time(uint32 time);
  uint32 get_time();
  // --- Constructors ---
  Api() = delete;
  Api(uint64 base, std::shared_ptr<Game> game);
  Api(Api &&) = default;
  Api(const Api &) = default;
  Api &operator=(Api &&) = default;
  Api &operator=(const Api &) = default;
  ~Api();

private:
  static std::unordered_map<std::string, Spell> spells_;
  static std::shared_ptr<Player> player_;

private:
  std::vector<std::shared_ptr<Item>> container_items_;
  std::vector<std::shared_ptr<Item>> equip_items_;
  std::vector<std::shared_ptr<Unit>> units_;
  std::vector<std::shared_ptr<Ground>> grounds_;
  std::shared_ptr<ItemCache> item_cache_;
  uint32 time_{0}; // 脚本运行时间
  uint64 base_;
  std::shared_ptr<Game> game_;
};
